# -*- coding: utf-8 -*-
# @Time    : 2024/6/12 16:33
# @Author  : yujiahao
# @File    : 18_function_built.py
# @description: Python中的内置函数

'''
Python将一些常用的功能（比如len）封装成了内置函数供我们使用，这些函数不仅效率高（底层用C语言实现），
而且拿来即用，避免重复造轮子。目前为止，Python 3.12.4 提供了 75 个内置函数。
有兴趣可以查看官网：https://docs.python.org/3/library/functions.html
还有网上的一个思维导图：https://www.processon.com/view/link/5b4ee15be4b0edb750de96ac
'''

# 常用内置函数

# abs()
# 功能: 返回一个数的绝对值
# 语法: abs(x)
# 注意: 适用于整数和浮点数
print(abs(-5))  # 输出: 5

# all()
# 功能: 如果可迭代对象中的所有元素都为真，则返回 True
# 语法: all(iterable)
# 注意: 空的可迭代对象返回 True
print(all([True, True, False]))  # 输出: False

# any()
# 功能: 如果可迭代对象中的任意元素为真，则返回 True
# 语法: any(iterable)
# 注意: 空的可迭代对象返回 False
print(any([False, False, True]))  # 输出: True

# bin()
# 功能: 将一个整数转换为其二进制表示
# 语法: bin(x)
# 注意: 返回值是一个字符串，以 '0b' 开头
print(bin(10))  # 输出: '0b1010'

# bool()
# 功能: 将一个值转换为布尔类型
# 语法: bool(x)
# 注意: 0、空对象和 None 转换为 False，其余为 True
print(bool(0))  # 输出: False

# bytearray()
# 功能: 返回一个新的字节数组
# 语法: bytearray([source[, encoding[, errors]]])
# 注意: 字节数组是可变的
b = bytearray(b"hello")
b[0] = ord('H')
print(b)  # 输出: bytearray(b'Hello')

# bytes()
# 功能: 返回一个新的不可变字节序列
# 语法: bytes([source[, encoding[, errors]]])
# 注意: 字节序列是不可变的
print(bytes("hello", "utf-8"))  # 输出: b'hello'

# callable()
# 功能: 检查对象是否可调用
# 语法: callable(object)
# 注意: 函数和方法是可调用的，普通对象不是
print(callable(len))  # 输出: True

# chr()
# 功能: 返回整数对应的字符
# 语法: chr(i)
# 注意: 整数必须在有效的 Unicode 范围内
print(chr(97))  # 输出: 'a'

# dict()
# 功能: 创建一个字典
# 语法: dict([mapping_or_iterable[, **kwargs]])
# 注意: 可以使用关键字参数或可迭代对象初始化字典
d = dict(a=1, b=2)
print(d)  # 输出: {'a': 1, 'b': 2}

# dir()
# 功能: 返回对象的属性和方法列表
# 语法: dir([object])
# 注意: 对于模块/类/对象，返回其属性、方法以及内置属性
print(dir([]))  # 输出: 列出列表对象的属性和方法

# enumerate()
# 功能: 返回一个枚举对象
# 语法: enumerate(iterable, start=0)
# 注意: 常用于在循环中获取索引和值
for i, value in enumerate(['a', 'b', 'c']):
    print(i, value)  # 输出: 0 a, 1 b, 2 c

# filter()
# 功能: 构建一个由函数筛选后的元素组成的迭代器
# 语法: filter(function, iterable)
# 注意: 函数返回 True 的元素才会包含在结果中
result = filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
print(list(result))  # 输出: [2, 4]

# float()
# 功能: 将一个字符串或数转换为浮点数
# 语法: float(x)
# 注意: 非法的字符串会引发 ValueError
print(float("1.23"))  # 输出: 1.23

# format()
# 功能: 格式化字符串
# 语法: format(value, format_spec)
# 注意: 使用格式说明符进行格式化
print(format(122, ">20"))  # 输出: '                 122'
print(format(122, "<20"))  # 输出: '122                 '
print(format(122, "^20"))  # 输出: '        122         '


# getattr()
# 功能: 获取对象的属性值
# 语法: getattr(object, name[, default])
# 注意: 如果属性不存在，会引发 AttributeError
class Test:
    x = 1


t = Test()
print(getattr(t, 'x'))  # 输出: 1

# globals()
# 功能: 返回当前全局符号表的字典
# 语法: globals()
# 注意: 主要用于调试和动态代码执行
print(globals())  # 输出: 当前全局符号表的字典


# hasattr()
# 功能: 检查对象是否有指定的属性
# 语法: hasattr(object, name)
# 注意: 返回布尔值
class Test:
    x = 1


t = Test()
print(hasattr(t, 'x'))  # 输出: True

# hash()
# 功能: 返回对象的哈希值
# 语法: hash(object)
# 注意: 适用于可哈希对象，如字符串和数字
print(hash("hello"))  # 输出: 字符串的哈希值

# help()
# 功能: 调用内置的帮助系统
# 语法: help([object])
# 注意: 非常有用的调试和学习工具
help(len)  # 输出: len() 函数的帮助信息

# hex()
# 功能: 将整数转换为十六进制字符串
# 语法: hex(x)
# 注意: 返回值是一个字符串，以 '0x' 开头
print(hex(255))  # 输出: '0xff'

# id()
# 功能: 返回对象的唯一标识符
# 语法: id(object)
# 注意: 标识符在对象的生命周期内是唯一的
a = object()
print(id(a))  # 输出: 对象的唯一标识符

# input()
# 功能: 从标准输入读取一行
# 语法: input([prompt])
# 注意: 返回值是一个字符串
# name = input("Enter your name: ")
# print(f"Hello, {name}!")  # 输出: 用户输入的名字

# int()
# 功能: 将一个值转换为整数
# 语法: int(x)
# 注意: 非法的字符串会引发 ValueError
print(int("123"))  # 输出: 123

# isinstance()
# 功能: 检查对象是否是指定类的实例
# 语法: isinstance(object, classinfo)
# 注意: 可以检查多个类的元组
print(isinstance(123, int))  # 输出: True


# issubclass()
# 功能: 检查一个类是否是另一个类的子类
# 语法: issubclass(class, classinfo)
# 注意: 可以检查多个类的元组
class A:
    pass


class B(A):
    pass


print(issubclass(B, A))  # 输出: True

# len()
# 功能: 返回对象的长度
# 语法: len(s)
# 注意: 适用于字符串、列表、元组等
print(len("hello"))  # 输出: 5

# list()
# 功能: 创建一个列表
# 语法: list([iterable])
# 注意: 可以从可迭代对象创建列表
print(list("hello"))  # 输出: ['h', 'e', 'l', 'l', 'o']

# map()
# 功能: 将函数应用于可迭代对象的每个元素
# 语法: map(function, iterable, ...)
# 注意: 返回一个迭代器
result = map(lambda x: x * 2, [1, 2, 3])
print(list(result))  # 输出: [2, 4, 6]

# max()
# 功能: 返回可迭代对象中的最大值
# 语法: max(iterable, *[, key, default])
# 注意: 可以接受多个参数
print(max([1, 2, 3]))  # 输出: 3

# min()
# 功能: 返回可迭代对象中的最小值
# 语法: min(iterable, *[, key, default])
# 注意: 可以接受多个参数
print(min([1, 2, 3]))  # 输出: 1
# 按照绝对值的大小，返回此序列最小值 min max相同
ret = min([1,2,-5,],key=abs)
print(ret)

# 加key是可以加函数名，min自动会获取传入函数中的参数的每个元素，然后通过你设定的返回值比较大小，返回最小的传入的那个参数。
print(min(1,2,-5,6,-3,key=lambda x:abs(x)))  # 可以设置很多参数比较大小
dic = {'a':3,'b':2,'c':1}
print(min(dic,key=lambda x:dic[x]))

# x为dic的key，lambda的返回值（即dic的值进行比较）返回最小的值对应的键



# reduce() 需要导包 这个在flink中是有状态算子，就是中间的值会保留然后后面会更新
# 语法： reduce(函数名,可迭代对象) # 这两个参数必须都要有,缺一个不行
'''
在Python2.x版本中recude是直接 import就可以的, Python3.x版本中需要从functools这个包中导入
reduce的作用是先把列表中的前俩个元素取出计算出一个值然后临时保存着,
接下来用这个临时保存的值和列表中第三个元素进行计算,求出一个新的值将最开始
临时保存的值覆盖掉,然后在用这个新的临时值和列表中第四个元素计算.依次类推

注意:我们放进去的可迭代对象没有更改
以上这个例子我们使用sum就可以完全的实现了.我现在有[1,2,3,4]想让列表中的数变成1234,就要用到reduce了.

'''
from functools import reduce
ret = reduce(lambda x, y: x + y, [3, 4, 5, 6, 7])
print(ret)  # 结果 25

# 普通函数版 主要看计算过程
from functools import reduce

def func(x,y):

    return x * 10 + y
    # 第一次的时候 x是1 y是2  x乘以10就是10,然后加上y也就是2最终结果是12然后临时存储起来了
    # 第二次的时候x是临时存储的值12 x乘以10就是 120 然后加上y也就是3最终结果是123临时存储起来了
    # 第三次的时候x是临时存储的值123 x乘以10就是 1230 然后加上y也就是4最终结果是1234然后返回了

l = reduce(func,[1,2,3,4])
print(l)


# next()
# 功能: 返回迭代器的下一个项目
# 语法: next(iterator[, default])
# 注意: 如果没有下一个项目，会引发 StopIteration
it = iter([1, 2, 3])
print(next(it))  # 输出: 1

# object()
# 功能: 返回一个新的空对象
# 语法: object()
# 注意: 通常用作基类
obj = object()
print(obj)  # 输出: <object object at 0x...>

# open()
# 功能: 打开一个文件并返回文件对象
# 语法: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
# 注意: 使用后需要关闭文件，建议使用 with 语句
with open("test.txt", "w") as f:
    f.write("hello")

# ord()
# 功能: 返回字符的 Unicode 码点
# 语法: ord(c)
# 注意: 适用于单个字符
print(ord('a'))  # 输出: 97

# pow()
# 功能: 返回 x 的 y 次幂
# 语法: pow(x, y[, z])
# 注意: 可以接受三个参数，计算 (x ** y) % z
print(pow(2, 3))  # 输出: 8

# print()
# 功能: 将对象打印到标准输出
# 语法: print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
# 注意: 可以使用 sep 和 end 参数自定义输出
''' 源码分析
def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    file:  默认是输出到屏幕，如果设置为文件句柄，输出到文件
    sep:   打印多个值之间的分隔符，默认为空格
    end:   每一次打印的结尾，默认为换行符
    flush: 立即把内容输出到流文件，不作缓存
    """
'''
print(111, 222, 333, sep='*')  # 111*222*333
print(111, end='')
print(222)  # 两行的结果 111222

# range()
# 功能: 返回一个不可变的数值序列
# 语法: range(stop) 或 range(start, stop[, step])
# 注意: 常用于循环
print(list(range(5)))  # 输出: [0, 1, 2, 3, 4]

# repr()
# 功能: 返回对象的字符串表示
# 语法: repr(object)
# 注意: 适用于调试
print(repr("hello"))  # 输出: "'hello'"

# reversed()
# 功能: 返回一个反向迭代器
# 语法: reversed(seq)
# 注意: 适用于序列
print(list(reversed([1, 2, 3])))  # 输出: [3, 2, 1]

# round()
# 功能: 返回浮点数的四舍五入值
# 语法: round(number[, ndigits])
# 注意: 可以指定小数点后的位数
print(round(2.675, 2))  # 输出: 2.67

# set()
# 功能: 创建一个新的集合
# 语法: set([iterable])
# 注意: 集合中的元素是唯一的
print(set([1, 2, 2, 3]))  # 输出: {1, 2, 3}


# setattr()
# 功能: 设置对象的属性值
# 语法: setattr(object, name, value)
# 注意: 如果属性不存在，会创建新属性
class Test:
    pass


t = Test()
setattr(t, 'x', 1)
print(t.x)  # 输出: 1

# sorted()
# 功能: 返回排序后的列表
# 语法: sorted(iterable, *, key=None, reverse=False)
# 注意: 原列表不变
'''
iterable : 可迭代对象
key: 排序规则(排序函数),在sorted内部会将可迭代对象中的每一个元素传递给这个函数的参数.根据函数运算的结果进行排序
reverse :是否是倒序,True 倒序 False 正序'''
print(sorted([3, 1, 2]))  # 输出: [1, 2, 3]

# 和函数组合使用

# 定义一个列表,然后根据一元素的长度排序
lst = ['天龙八部','西游记','红楼梦','三国演义']

# 计算字符串的长度
def func(s):
    return len(s)
print(sorted(lst,key=func))

# 结果:
# ['西游记', '红楼梦', '天龙八部', '三国演义']


# 和lambda组合使用

lst = ['天龙八部','西游记','红楼梦','三国演义']

print(sorted(lst,key=lambda s:len(s)))


lst = [{'id':1,'name':'alex','age':18},
    {'id':2,'name':'wusir','age':17},
    {'id':3,'name':'taibai','age':16},]

# 按照年龄对学生信息进行排序

print(sorted(lst,key=lambda e:e['age']))


# staticmethod()
# 功能: 将方法转换为静态方法
# 语法: staticmethod(function)
# 注意: 静态方法不需要类实例
class Test:
    @staticmethod
    def hello():
        print("Hello")


Test.hello()  # 输出: Hello

# str()
# 功能: 将对象转换为字符串
# 语法: str(object='')
# 注意: 常用于字符串表示
print(str(123))  # 输出: '123'

# sum()
# 功能: 返回可迭代对象中元素的和
# 语法: sum(iterable, /, start=0)
# 注意: 可以指定起始值
print(sum([1, 2, 3]))  # 输出: 6


# super()
# 功能: 返回父类的一个代理对象
# 语法: super([type[, object-or-type]])
# 注意: 常用于调用父类的方法
class A:
    def hello(self):
        print("Hello from A")


class B(A):
    def hello(self):
        super().hello()
        print("Hello from B")


b = B()
b.hello()
# 输出:
# Hello from A
# Hello from B

# tuple()
# 功能: 创建一个新的元组
# 语法: tuple([iterable])
# 注意: 元组是不可变的
print(tuple([1, 2, 3]))  # 输出: (1, 2, 3)

# type()
# 功能: 返回对象的类型
# 语法: type(object) 或 type(name, bases, dict)
# 注意: 也可以用来创建新类
print(type(123))  # 输出: <class 'int'>

# zip()
# 功能: 将可迭代对象打包成元组的迭代器
# 语法: zip(*iterables)
# 注意: 返回的迭代器长度与最短的输入序列相同
print(list(zip([1, 2, 3], ['a', 'b', 'c'])))  # 输出: [(1, 'a'), (2, 'b'), (3, 'c')]

# 不常用内置函数

# aiter()
# 功能: 返回异步迭代器
# 语法: aiter(async_iterable)
# 注意: 适用于异步生成器
import asyncio


async def async_gen():
    yield 1
    yield 2


async def main():
    async for i in aiter(async_gen()):
        print(i)


# asyncio.run(main())  # 输出: 1, 2

# 工作中禁止使用
"""
在工作中建议禁止使用 eval() 和 exec() 的原因主要是出于安全性考虑。
虽然这两个函数在某些情况下非常强大和灵活，但它们也带来了巨大的安全风险，
特别是在处理不可信输入时。

虽然 eval() 很方便，但它也非常危险，因为它会执行传入的字符串表达式。
如果这个字符串包含恶意代码，eval() 将会执行这些代码，可能导致严重的安全漏洞。例如：

    user_input = "os.system('rm -rf /')"  # 恶意输入
    eval(user_input)  # 这将会执行删除所有文件的命令

同样，exec() 也非常危险，因为它可以执行任何传入的代码。
如果传入的代码包含恶意内容，可能导致系统被攻击或数据被破坏。例如：

    user_input = "os.system('rm -rf /')"  # 恶意输入
    exec(user_input)  # 这将会执行删除所有文件的命令

安全风险：
1. 代码注入攻击：如果用户输入未经验证就传递给 eval() 或 exec()，攻击者可以注入恶意代码并执行。
2. 权限提升：恶意代码可能利用这些函数提升权限，执行系统命令或访问敏感数据。
3. 数据泄露：攻击者可以通过这些函数访问和泄露数据。

安全替代方案：
1. 安全评估：如果必须使用 eval() 或 exec()，确保输入是完全可信的，并严格控制输入内容。
2. 限制功能：使用 ast.literal_eval() 来安全地评估字符串表达式，只允许字面值（如数字、字符串、元组、列表、字典等）：

    import ast
    safe_input = "{'key': 'value'}"
    result = ast.literal_eval(safe_input)
    print(result)  # 输出: {'key': 'value'}

3. 自定义解析：根据具体需求，手动解析和处理输入，而不是使用 eval() 或 exec()。
"""

# eval()
# 功能: 执行表达式并返回结果
# 语法: eval(expression, globals=None, locals=None)
# 注意: 仅限于可信的输入，避免安全问题
x = 1
print(eval('x + 1'))  # 输出: 2

# exec
# 功能: 执行字符串类型的代码
# 语法: exec(object[, globals[, locals]])
# 注意: 工作中禁止使用，出于安全性考虑
s = '''
for i in [1, 2, 3]:
    print(i)
'''
exec(s)
